#include "POVObject.h"

#include "../glutil/GLee.h"

#include <QFutureWatcher>
#include <QGLWidget>
#include <QtConcurrentMap>
#include <QTime>

#include <math.h>
#include <float.h>
#include "POVMesh.h"
#include "../geom/Ray.h"
#include "../geom/Octree.h"
#include "../geom/Triangle.h"
#include "../geom/PolyModel.h"
#include "../AOProgressDialog.h"

using namespace POVGeom;

POVObject::POVObject()
{
}

POVObject::POVObject(const geom::PolyModel &pm)
{
	
	for(int i=0;i<pm.numberOfMeshes();i++)
    	m_meshes.push_back(pm.getMesh(i));
	setName(pm.name());
}

POVObject::~POVObject()
{
}

#define MAX(X,Y)  (X)>(Y)?(X):(Y)

BBox POVObject::getObjectBBox()
{
	Point3D minP(FLT_MAX, FLT_MAX, FLT_MAX);
	Point3D maxP(-FLT_MAX, -FLT_MAX, -FLT_MAX);
	BBox result(Point3D(0,0,0),0.1);
	for(unsigned int i=0;i<m_meshes.size();++i)
		result+=m_meshes.at(i).getMeshBoundingBox();

	return result;
}

void POVObject::generateAO(Octree<Triangle> * oct, int numRays, AOProgressDialog * progress)
{
	int numMeshes = numberOfMeshes();
	for(int i=0;i<numMeshes;i++)
		//if(true||!m_meshes.at(i).hasNormals())
			m_meshes.at(i).generateNormals();
//			POVMesh(&m_meshes.at(i)).generateNormals();

	if(numRays!=0)
		for(int i=0;i<numMeshes;++i)
			POVMesh(&m_meshes.at(i)).addMeshToOctree(oct);
	BBox octBox = oct->getBBox();

	Point3D p1(octBox.m_center.x - octBox.m_side*0.499, 0,octBox.m_center.z-octBox.m_side * 0.499);
	Point3D p2(octBox.m_center.x + octBox.m_side*0.499, 0,octBox.m_center.z-octBox.m_side*0.499);
	Point3D p3(0, 0,octBox.m_center.z + octBox.m_side * 0.499);
	Triangle t(p1,p2,p3);
	oct->addObject(t);
	for(int i=0;i<numMeshes;++i)
		POVMesh(&m_meshes.at(i)).generateAmbientOcclusion(oct, numRays, progress,i);
}

void POVObject::setPartColor(string name, float * color)
{
	for(unsigned int i=0; i<m_meshes.size();++i)
		if(m_meshes.at(i).name() == name)
			m_meshes.at(i).setBaseColor(color[0],color[1],color[2]);
}

auto_ptr<PolyModel> POVObject::convertToPolyModel() const
{
	auto_ptr<PolyModel> pm(new PolyModel());
	for(unsigned int i=0;i<m_meshes.size();i++)
		pm->addMesh(m_meshes.at(i));
	pm->setName(name());
	return pm;
}

